#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <signal.h> // Optional: For handling Ctrl+C gracefully

#include "ReaderWriterUtilities.h"
#include "Reader.h"
#include "Writer.h"

#define READER_NUMBER 5 // 读者数量
#define WRITER_NUMBER 2 // 写者数量

// Global pointer to manager for signal handling (optional)
ReaderWriterManager_t *g_rwMgr = NULL;

// Optional: Signal handler for graceful exit
void handle_sigint(int sig) {
    printf("\nCtrl+C detected. Signaling threads to exit...\n");
    if (g_rwMgr != NULL) {
        g_rwMgr->exit_flag = 1;
    }
    // Note: Semaphores might still block exit if threads are waiting.
    // A more robust solution might involve pthread_cancel or checking flags more often.
}

int main(int argc, char *argv[]) {
    int idx = 0;
    ThreadStruct_t *readerThreads = NULL;
    ThreadStruct_t *writerThreads = NULL;
    ReaderWriterManager_t *rwMgr = NULL;

    // Optional: Setup signal handler
    signal(SIGINT, handle_sigint);

    // 分配内存
    readerThreads = (ThreadStruct_t *)malloc(sizeof(ThreadStruct_t) * READER_NUMBER);
    writerThreads = (ThreadStruct_t *)malloc(sizeof(ThreadStruct_t) * WRITER_NUMBER);

    //  创建并初始化共享管理器
    rwMgr = createReaderWriterManager();
    g_rwMgr = rwMgr; // Store globally for signal handler

    if (readerThreads == NULL || writerThreads == NULL || rwMgr == NULL) {
        perror("Malloc or createManager failed!"); // [Source 5, 37]
        // Basic cleanup
        free(readerThreads);
        free(writerThreads);
        if (rwMgr) {
             semDestroy(&rwMgr->rw_mutex);
             semDestroy(&rwMgr->mutex);
             free(rwMgr);
        }
        exit(EXIT_FAILURE);
    }

    printf("Starting %d Readers and %d Writers...\n", READER_NUMBER, WRITER_NUMBER);
    printf("Press Ctrl+C to signal exit (or wait for program end if signal handler not used).\n");

    // 创建读者线程
    for (idx = 0; idx < READER_NUMBER; ++idx) {
        initThreadStruct(&readerThreads[idx], rwMgr, idx);
        if (pthread_create(&readerThreads[idx].tid, NULL, readerThread, (void *)&readerThreads[idx]) != 0) {
            perror("Failed to create reader thread");
             // Handle error appropriately - maybe set exit flag and clean up
            rwMgr->exit_flag = 1;
            break; // Stop creating more threads
        }
    }

    // 创建写者线程
    for (idx = 0; idx < WRITER_NUMBER; ++idx) {
         if (rwMgr->exit_flag) break; // Don't create if error occurred
        initThreadStruct(&writerThreads[idx], rwMgr, idx);
        if (pthread_create(&writerThreads[idx].tid, NULL, writerThread, (void *)&writerThreads[idx]) != 0) {
             perror("Failed to create writer thread");
             rwMgr->exit_flag = 1; // Signal others to exit
             break;
        }
    }


    //等待退出
    while(rwMgr->exit_flag == 0) {
        sleep(1); // Check exit flag periodically
    }
    printf("Main thread detected exit signal. Waiting for threads to join...\n");


    // Wait for Reader threads to exit [Source 8, 40]
    printf("Waiting for Readers...\n");
    for (idx = 0; idx < READER_NUMBER; ++idx) {
         // Only join threads that were successfully created
        if (readerThreads[idx].tid != 0) { // Simple check if tid was set
            pthread_join(readerThreads[idx].tid, NULL); //  等待所有子线程执行完毕
        }
    }

    // 回收线程
    printf("Waiting for Writers...\n");
    for (idx = 0; idx < WRITER_NUMBER; ++idx) {
        if (writerThreads[idx].tid != 0) {
            pthread_join(writerThreads[idx].tid, NULL);
        }
    }

    printf("All threads have joined. Cleaning up.\n");

    // 资源释放
    free(readerThreads);
    free(writerThreads);

    // Destroy semaphores before freeing manager memory [Source 40]
    semDestroy(&rwMgr->rw_mutex);
    semDestroy(&rwMgr->mutex);

    free(rwMgr);
    g_rwMgr = NULL;

    printf("Reader-Writer simulation finished.\n");
    return 0; // Use 0 for successful exit
}
